package com.easylinkin.linkappapi.common.utils;


import org.apache.commons.net.util.Base64;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;

import javax.crypto.Mac;
import javax.crypto.spec.SecretKeySpec;
import java.security.MessageDigest;

public class DigestUtil {
    private enum DigestType{

        MD5("MD5")
        ,SHA("SHA")
        ,SHA256("SHA-256")
        ,SHA512("SHA-512");

        private String digestDesc;

        private DigestType(String digestDesc){
            this.digestDesc = digestDesc;
        }

        public String getDigestDesc() {
            return digestDesc;
        }
    }

    private final static String digest(String sourceStr,DigestType type) {
        char[] hexDigits = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
        try {
            byte[] btInput = sourceStr.getBytes();
            // 获得MD5摘要算法的 MessageDigest 对象
            MessageDigest mdInst = MessageDigest.getInstance(type.digestDesc);
            // 使用指定的字节更新摘要
            mdInst.update(btInput);
            // 获得密文
            byte[] md = mdInst.digest();
            // 把密文转换成十六进制的字符串形式
            int j = md.length;
            char[] str = new char[j * 2];
            int k = 0;
            for (int i = 0; i < j; i++) {
                byte byte0 = md[i];
                str[k++] = hexDigits[byte0 >>> 4 & 0xf];
                str[k++] = hexDigits[byte0 & 0xf];
            }
            return new String(str);
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    public final static String MD5(String s) {
        return digest(s, DigestType.MD5);
    }

    public final static String SHA(String s) {
        return digest(s, DigestType.SHA);
    }

    public final static String SHA256(String s){
        return digest(s, DigestType.SHA256);
    }

    public final static String SHA512(String s){
        return digest(s, DigestType.SHA512);
    }

    /**
     * 生成签名
     * @param params
     * @param appSecret
     * @return
     */
    public  final static  String hmacSHA256Sign(String params,String appSecret){
        try {
            Mac hmacSha256 = Mac.getInstance("HmacSHA256");
            byte[] keyBytes = appSecret.getBytes("UTF-8");
            hmacSha256.init(new SecretKeySpec(keyBytes, 0, keyBytes.length, "HmacSHA256"));
            String sign = new String(Base64.encodeBase64(hmacSha256.doFinal(params.getBytes("UTF-8")),true));
            return sign;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return  null;
    }




    public static void main(String[] args) {
        String sourceStr1 = "20121221";
        String sourceStr2 = "Digest Str......";

//        System.out.println(DigestUtil.MD5(sourceStr1));
//        System.out.println(DigestUtil.MD5(sourceStr2));
//
//        System.out.println(DigestUtil.SHA(sourceStr1));
//        System.out.println(DigestUtil.SHA(sourceStr2));

//        System.out.println(DigestUtil.SHA256(sourceStr1));
//        System.out.println(DigestUtil.SHA256(sourceStr2));

//        System.out.println(DigestUtil.SHA512(sourceStr1));
//        System.out.println(DigestUtil.SHA512(sourceStr2));
//        System.out.println(hmacSHA256Sign("dsdsdsds","sdsdfdfgfgfgf"));
        bcryptTest();

    }

    public static void bcryptTest() {

        String password = "12345";
        PasswordEncoder passwordEncoder = PasswordEncoderFactories.createDelegatingPasswordEncoder();
        String encodePsw = passwordEncoder.encode(password);
        passwordEncoder.matches(password, encodePsw);
        // 新密码与旧密码一样
        if (bcryptMatches(password, encodePsw)) {
            System.out.println("match!:\n" + password + ":" + encodePsw);
        }
        // 使用BCrypt加密测试每次是否相同
//        for (int i = 0; i < 20; i++) {
//            String passwordEncoded = passwordEncoder.encode(password);
//            System.out.println(passwordEncoded);
//        }

    }

    /**
     * 判断bcrypt 密文和原文是否匹配
     * @param rawPassword 明文密码
     * @param encodedPassword 密文
     * @return
     */
    public static boolean bcryptMatches(CharSequence rawPassword, String encodedPassword) {
        return PasswordEncoderFactories.createDelegatingPasswordEncoder().matches(rawPassword, encodedPassword);
    }

}
